package org.tlang.metaclass;

import org.tlang.ast.list.func.ArgumentList;
import org.tlang.context.ValueTable;
import org.tlang.exception.EvalException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TNativeFunction implements TFunction {
    private final String name; // for debug
    private final Method method;
    private final int numParameters;

    public TNativeFunction(Method method, String name) {
        this.method = method;
        this.name = name;
        this.numParameters = method.getParameterTypes().length;
    }

    @Override
    public String toString() {
        return "<native function: " + this.name + "(" + hashCode() + ")>";
    }

    @Override
    public Object execute(ValueTable callerValueTable, ArgumentList arguments) {
        Object[] args = new Object[numParameters];
        for (int i = 0; i < args.length; i++) {
            Object value = arguments.child(i).eval(callerValueTable);
            if (value instanceof TGetter) {
                value = ((TGetter) value).get();
            }
            args[i] = value;
        }

        try {
            return method.invoke(null, args);
        } catch (InvocationTargetException | IllegalAccessException e) {
            throw new EvalException("native function: \"" + name + "\" invoke error: " + e.getMessage(), arguments);
        }
    }
}
